#include "stdafx.h"
#include "GraphicsClass.h"


CGraphicsClass::CGraphicsClass(void) : m_pD3D(nullptr), m_pCamera(nullptr), m_pModel(nullptr), /*m_pColorShader(nullptr),*/ m_pTextureShader(nullptr), m_pLightShader(nullptr), m_pLight(nullptr), m_pBitmap(nullptr), m_pText(nullptr),
	m_pModelList(nullptr), m_pFrustum(nullptr)
{
}


CGraphicsClass::~CGraphicsClass(void)
{
}

bool CGraphicsClass::Initialize(int nScreenWidth, int nScreenHeight, HWND hWnd)
{
	bool bResult = false;
	D3DXMATRIX d3dBaseViewMatrix;

	m_pD3D = new CD3DClass();
	if(m_pD3D == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the D3D pointer");
		return false;
	}

	bResult = m_pD3D->Initialize(nScreenWidth, nScreenHeight, VSYNC_ENABLED, hWnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize Direct3D");
		return false;
	}

	m_pMayaModel = new CMayaModel();
	if(m_pMayaModel == nullptr)
	{
		DEBUG_OUTPUT("Failed to create maya model pointer");
		return false;
	}

	bResult = m_pMayaModel->LoadModel("../Resources/Models/Maya/cubetest.obj");
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to load maya model");
		return false;
	}

	m_pCamera = new CCameraClass();
	if(m_pCamera == nullptr)
	{
		DEBUG_OUTPUT("Failed to create camera");
		return false;
	}

	m_pCamera->SetPosition(0, 0, -10.0f);
	m_pCamera->Render();
	m_pCamera->GetViewMatrix(d3dBaseViewMatrix);

	m_pModel = new CModelClass();
	if(m_pModel == nullptr)
	{
		DEBUG_OUTPUT("Failed to create model pointer");
		return false;
	}

	m_pText = new CTextClass();
	if(m_pText == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the text pointer");
		return false;
	}

	bResult = m_pText->Initialize(m_pD3D->GetDevice(), m_pD3D->GetDeviceContext(), hWnd, nScreenWidth, nScreenHeight, d3dBaseViewMatrix);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize text pointer");
		return false;
	}

	bResult = m_pModel->Initialize(m_pD3D->GetDevice(),"../Resources/Models/Maya/model.txt", L"../Resources/DDS/seafloor.dds");
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize model");
		return false;
	}

	//m_pColorShader = new CColorShaderClass();
	//if(m_pColorShader == nullptr)
	//{
	//	DEBUG_OUTPUT("Failed to create color shader pointer");
	//	return false;
	//}

	//bResult = m_pColorShader->Initialize(m_pD3D->GetDevice(), hWnd);
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to initialize color shader");
	//	return false;
	//}

	m_pLightShader = new CLightShaderClass();
	if(m_pLightShader == nullptr)
	{
		DEBUG_OUTPUT("Failed to create light shader pointer");
		return false;
	}
	
	bResult = m_pLightShader->Initialize(m_pD3D->GetDevice(), hWnd);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize light shader");
		return false;
	}
	
	m_pLight = new CLightClass();
	if(m_pLight == nullptr)
	{
		DEBUG_OUTPUT("Failed to create light pointer");
		return false;
	}
	
	m_pLight->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
	m_pLight->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
	m_pLight->SetDirection(0.0f, 0.0f, 1.0f);
	m_pLight->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f);
	m_pLight->SetSpecularPower(32.0f);
	
	m_pTextureShader = new CTextureShaderClass();
	if(m_pTextureShader == nullptr)
	{
		DEBUG_OUTPUT("Failed to create texture shader pointer");
		return false;
	}
	
	bResult = m_pTextureShader->Initialize(m_pD3D->GetDevice(), hWnd);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize texture shader");
		return false;
	}
	
	m_pBitmap = new CBitmapClass();
	if(m_pBitmap == nullptr)
	{
		DEBUG_OUTPUT("Failed to create bitmap class pointer");
		return false;
	}
	
	bResult = m_pBitmap->Initialize(m_pD3D->GetDevice(), nScreenWidth, nScreenHeight, L"../Resources/DDS/seafloor.dds", 256, 256);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed  to initialize bitmap pointer");
		return false;
	}

	m_pModelList = new CModelListClass();
	if(m_pModelList == nullptr)
	{
		DEBUG_OUTPUT("Failed  to create model list pointer");
		return false;
	}

	bResult = m_pModelList->Initialize(25);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed  to initialize model list pointer");
		return false;
	}

	m_pFrustum = new CFrustumClass();
	if(m_pFrustum == nullptr)
	{
		DEBUG_OUTPUT("Failed  to create frustum pointer");
		return false;
	}

	return true;
}

void CGraphicsClass::ShutDown()
{
	if(m_pFrustum)
	{
		delete m_pFrustum;
		m_pFrustum = nullptr;
	}

	if(m_pModelList)
	{
		m_pModelList->ShutDown();
		delete m_pModelList;
		m_pModelList = nullptr;
	}
	
	if(m_pText)
	{
		m_pText->ShutDown();
		delete m_pText;
		m_pText = nullptr;
	}

	if(m_pCamera)
	{
		delete m_pCamera;
		m_pCamera = nullptr;
	}

	if(m_pBitmap)
	{
		m_pBitmap->ShutDown();
		delete m_pBitmap;
		m_pBitmap = 0;
	}
	
	if(m_pLight)
	{
		delete m_pLight;
		m_pLight = 0;
	}
	
	if(m_pLightShader)
	{
		m_pLightShader->ShutDown();
		delete m_pLightShader;
		m_pLightShader = 0;
	}
	
	if(m_pTextureShader != nullptr)
	{
		m_pTextureShader->ShutDown();
		delete m_pTextureShader;
		m_pTextureShader = nullptr;
	}

	//if(m_pColorShader)
	//{
	//	delete m_pColorShader;
	//	m_pColorShader = nullptr;
	//}

	if(m_pModel)
	{
		m_pModel->ShutDown();
		delete m_pModel;
		m_pModel = nullptr;
	}

	if(m_pCamera)
	{
		delete m_pCamera;
		m_pCamera = nullptr;
	}

	if(m_pD3D)
	{
		m_pD3D->ShutDown();
		delete m_pD3D;
		m_pD3D = nullptr;
	}
}

bool CGraphicsClass::Frame(float fYRot)
{
	bool bResult = false;

	//bResult = m_pText->SetMousePosition(nXPos, nYPos, m_pD3D->GetDeviceContext());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to set the mouse position");
	//	return false;
	//}

	//bResult = m_pText->SetFPS(nFPS, m_pD3D->GetDeviceContext());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to set the fps");
	//	return false;
	//}
	//
	//bResult = m_pText->SetCPU(nCPUPercent, m_pD3D->GetDeviceContext());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to set the cpu percentage");
	//	return false;
	//}

	m_pCamera->SetPosition(0.0f, 0.0f, -10.0f);
	m_pCamera->SetRotation(0.0f, fYRot, 0.0f);
	
	//static float fRotation = 0.0f;
	//
	//fRotation += (float)D3DX_PI * 0.005f;
	//if(fRotation > 360)
	//{
	//	fRotation = 0.0f;
	//}
	//
	//bResult = Render(fRotation);
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render scene");
	//	return false;
	//}

	return true;
}

bool CGraphicsClass::Render(/*float fRotation*/)
{
	D3DXMATRIX d3dWorldMatrix;
	D3DXMATRIX d3dViewMatrix;
	D3DXMATRIX d3dProjectionMatrix;
	D3DXMATRIX d3dOrthographicMatrix;
	D3DXVECTOR4 d3dColor;
	int nModelCount;
	int nRenderCount;
	float fXPos;
	float fYPos;
	float fZPos;
	float fRadius;
	bool bResult = false;
	bool bRenderModel = false;

	m_pD3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

	m_pCamera->Render();

	m_pCamera->GetViewMatrix(d3dViewMatrix);
	m_pD3D->GetWorldMatrix(d3dWorldMatrix);
	m_pD3D->GetProjectionMatrix(d3dProjectionMatrix);
	m_pD3D->GetOrthographicMatrix(d3dOrthographicMatrix);

	m_pFrustum->ConstructFrustum(SCREEN_DEPTH, d3dProjectionMatrix, d3dViewMatrix);

	nModelCount = m_pModelList->GetModelCount();

	nRenderCount = 0;

	static float fRotation = 0.0f;
	
	fRotation += (float)D3DX_PI * 0.005f;
	if(fRotation > 360)
	{
		fRotation = 0.0f;
	}

	for(int i = 0; i < nModelCount; ++i)
	{
		m_pModelList->GetData(i, fXPos, fYPos, fZPos, d3dColor);

		fRadius = 1.0f;

		bRenderModel = m_pFrustum->CheckCube(fXPos, fYPos, fZPos, fRadius);

		if(bRenderModel == true)
		{
			D3DXMatrixTranslation(&d3dWorldMatrix, fXPos, fYPos, fZPos); 

			m_pModel->Render(m_pD3D->GetDeviceContext());

			m_pLightShader->Render(m_pD3D->GetDeviceContext(), m_pModel->GetIndexCount(), 
				d3dWorldMatrix, d3dViewMatrix, d3dProjectionMatrix, 
					      m_pModel->GetTexture(), m_pLight->GetDirection(), m_pLight->GetAmbientColor(),
						  d3dColor, m_pCamera->GetPosition(), m_pLight->GetSpecularColor(), m_pLight->GetSpecularPower());

			m_pD3D->GetWorldMatrix(d3dWorldMatrix);

			nRenderCount += 1;
		}
	}

	bResult = m_pText->SetRenderCount(nRenderCount, m_pD3D->GetDeviceContext());
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to set render count");
		return false;
	}

	m_pD3D->TurnZBufferOff();

	m_pD3D->TurnOnAlphaBlending();

	bResult = m_pText->Render(m_pD3D->GetDeviceContext(), d3dWorldMatrix, d3dOrthographicMatrix);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to render text");
		return false;
	}

	m_pD3D->TurnOffAlphaBlending();

	//bResult = m_pBitmap->Render(m_pD3D->GetDeviceContext(), 300, 300);
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render bitmap");
	//	return false;
	//}
	//
	//bResult = m_pTextureShader->Render(m_pD3D->GetDeviceContext(), m_pBitmap->GetIndexCount(), d3dWorldMatrix, d3dViewMatrix, d3dOrthographicMatrix, m_pBitmap->GetTexture());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render bitmap texture shader");
	//	return false;
	//}

	m_pD3D->TurnZBufferOn();
	
	//D3DXMatrixRotationY(&d3dWorldMatrix, fRotation);
	
	//m_pModel->Render(m_pD3D->GetDeviceContext());
	//
	//bResult = m_pLightShader->Render(m_pD3D->GetDeviceContext(), m_pModel->GetIndexCount(), d3dWorldMatrix, d3dViewMatrix, d3dProjectionMatrix, m_pModel->GetTexture(), m_pLight->GetDirection(), m_pLight->GetAmbientColor(), m_pLight->GetDiffuseColor(), m_pCamera->GetPosition(), m_pLight->GetSpecularColor(), m_pLight->GetSpecularPower());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render light shader");
	//	return false;
	//}
	
	//bResult = m_pColorShader->Render(m_pD3D->GetDeviceContext(), m_pModel->GetIndexCount(), d3dWorldMatrix, d3dViewMatrix, d3dProjectionMatrix);
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render color shader");
	//	return false;
	//}
	
	//bResult = m_pTextureShader->Render(m_pD3D->GetDeviceContext(), m_pModel->GetIndexCount(), d3dWorldMatrix, d3dViewMatrix, d3dProjectionMatrix, m_pModel->GetTexture());
	//if(bResult == false)
	//{
	//	DEBUG_OUTPUT("Failed to render texture shader");
	//	return false;
	//}

	m_pD3D->EndScene();

	return true;
}